package leetCode.thread.leetCode1195;

import java.util.concurrent.Semaphore;
import java.util.function.IntConsumer;

public class FizzBuzz1 implements FizzBuzz {

    private final int n;
    Semaphore fizz = new Semaphore(0);
    Semaphore buzz = new Semaphore(0);
    Semaphore fizzbuzz = new Semaphore(0);
    Semaphore number = new Semaphore(0);
    private volatile boolean stop = false;

    public FizzBuzz1(int n) {
        this.n = n;
    }

    // printFizz.run() outputs "fizz".
    public void fizz(Runnable printFizz) throws InterruptedException {
        for(int i=0;i<n;i++) {
            fizz.acquire();
            if(stop) break;
            printFizz.run();
            number.release();
        }
    }

    // printBuzz.run() outputs "buzz".
    public void buzz(Runnable printBuzz) throws InterruptedException {
        for(int i=0;i<n;i++) {
            buzz.acquire();
            if(stop) break;
            printBuzz.run();
            number.release();
        }
    }

    // printFizzBuzz.run() outputs "fizzbuzz".
    public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
        for(int i=0;i<n;i++) {
            fizzbuzz.acquire();
            if(stop) break;
            printFizzBuzz.run();
            number.release();
        }
    }

    // printNumber.accept(x) outputs "x", where x is an integer.
    public void number(IntConsumer printNumber) throws InterruptedException {
        for(int i=1;i<=n;i++) {
            if(i%3==0&&i%5==0){
                fizzbuzz.release();
                number.acquire();
            }
            else if(i%3==0){
                fizz.release();
                number.acquire();
            }
            else if(i%5==0){
                buzz.release();
                number.acquire();
            }
            else{
                printNumber.accept(i);
            }
            if(i==n){
                stop = true;
                fizz.release();
                buzz.release();
                fizzbuzz.release();
            }
        }
    }

}
